package com.jspx.txweb.dispatcher.handle;

import com.jspx.boot.environment.Environment;
import com.jspx.json.JSONException;
import com.jspx.json.JSONObject;
import com.jspx.json.XML;
import com.jspx.txweb.ActionInvocation;
import com.jspx.txweb.dispatcher.Dispatcher;
import com.jspx.txweb.proxy.DefaultActionInvocation;
import com.jspx.txweb.result.RocResult;
import com.jspx.txweb.util.RequestUtil;
import com.jspx.txweb.util.TXWebUtil;
import com.jspx.utils.StringUtil;
import com.jspx.utils.URLUtil;
import com.jspx.utils.XMLUtil;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

/**
 * Created by Administrator on 2017/6/17.
 * RPC ,ROC 调用
 */
public class RocHandle extends ActionHandle {
    final public static String name = "roc";
   static String getRequestReader(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String callStr = RequestUtil.getReader(request);
        ///////////////////读取ajax请求 end
        if (StringUtil.isNULL(callStr)) {
            JSONObject errorResultJson = TXWebUtil.createRocErrorInfo(URLUtil.getFileNamePart(request.getRequestURI()), -32600, "Invalid params.参数无效,无效的请求");
            TXWebUtil.print(errorResultJson.toString(4), TXWebUtil.jsonType, response);
            return null;
        }
        //////////////////初始begin
        if (callStr.length() > 20480) {
            JSONObject errorResultJson = TXWebUtil.createRocErrorInfo(URLUtil.getFileNamePart(request.getRequestURI()), -32600, "Invalid params.参数无效,长度超出范围");
            TXWebUtil.print(errorResultJson.toString(4), TXWebUtil.jsonType, response);
            return null;
        }
        return callStr;
    }

    public void doing(HttpServletRequest request, HttpServletResponse response) throws Exception {

        String callStr = getRequestReader( request, response);
        if (StringUtil.isNULL(callStr)) return;
        callAction(request, response, callStr, false);
    }

    void callAction(HttpServletRequest request, HttpServletResponse response, String call, boolean secret) throws Exception {
        //判断是XML还是JSON begin
        String rpc = StringUtil.trim(call);
        JSONObject jsonData = null;
        boolean jsonFormat = true;
        if (StringUtil.isXml(rpc)) {
            //XML格式
            try {
                jsonData = XML.toJSONObject(rpc);
            } catch (JSONException e) {
                JSONObject errorResultJson = TXWebUtil.createRocErrorInfo(URLUtil.getFileNamePart(request.getRequestURI()), -32600, "Invalid params.参数无效,无效的请求");
                TXWebUtil.print("<?xml version=\"1.0\" encoding=\"" + Dispatcher.getEncode() + "\"?>\r\n" + XMLUtil.format(XML.toString(errorResultJson, Environment.rocResult)), TXWebUtil.xmlType, response);
            }
            jsonFormat = false;

        }
        if (StringUtil.isJsonObject(rpc)) {
            //JSON格式
            try {
                jsonData = new JSONObject(rpc);
            } catch (JSONException e) {
                JSONObject errorResultJson = TXWebUtil.createRocErrorInfo(URLUtil.getFileNamePart(request.getRequestURI()), -32600, "Invalid params.参数无效,无效的请求");
                TXWebUtil.print(errorResultJson.toString(4), TXWebUtil.jsonType, response);
                return;
            }
        }

        if (jsonData == null) {
            JSONObject errorResultJson = TXWebUtil.createRocErrorInfo(URLUtil.getFileNamePart(request.getRequestURI()), -32600, "Invalid params.参数无效,不能识别的格式");
            TXWebUtil.print(errorResultJson.toString(4), TXWebUtil.jsonType, response);
            return;
        }
        //判断是XML还是JSON end

        JSONObject methodCall = jsonData.getJSONObject(Environment.rocMethodCall);
        //兼容格式调整
        if (methodCall != null) jsonData = methodCall;
        //////////////////初始end

        namespace = TXWebUtil.getNamespace(request.getServletPath());
        namePart = jsonData.getString(Environment.rocId);

        if (StringUtil.isNULL(namePart)) namePart = URLUtil.getFileNamePart(request.getRequestURI());
        if (namePart != null && namePart.contains(TXWebUtil.AT)) {
            namePart = StringUtil.substringBefore(namePart, TXWebUtil.AT);
            namespace = StringUtil.substringAfter(namePart, TXWebUtil.AT);
        }
        ///////////////////////////////////环境参数 begin

        Map<String, Object> envParams = createEnvironment(request,response);
        if (StringUtil.isNULL(jsonData.getString("id"))) jsonData.put("id", namePart);

        if (actionConfig == null) {
            envParams.clear();
            JSONObject errorResultJson = TXWebUtil.createRocErrorInfo(URLUtil.getFileNamePart(request.getRequestURI()), -32600, "class not found.找不到执行对象");
            TXWebUtil.print(errorResultJson.toString(4), TXWebUtil.jsonType, response);
            return;
        }

        if (actionConfig.isSecret() && !secret) {
            JSONObject errorResultJson = TXWebUtil.createRocErrorInfo(URLUtil.getFileNamePart(request.getRequestURI()), -32600, "forbidden not secret request call.禁止非加密方式调用");
            TXWebUtil.print(errorResultJson.toString(4), TXWebUtil.jsonType, response);
            return;
            //加密调用这里返回
        }
        if (!jsonData.containsKey(Environment.rocFormat))
            jsonData.put(Environment.rocFormat, jsonFormat ? "json" : "xml");

        //在高并发下，ajax请求会出现异常，必须使用synchronized
        //执行action返回数据begin
        synchronized(this)
        {
            ActionInvocation actionInvocation = new DefaultActionInvocation(actionConfig, envParams, jsonData, request, response);
            actionInvocation.initAction();
            actionInvocation.invoke();
            actionInvocation.executeResult(new RocResult());
        }
        //执行action返回数据end

    }
}
